/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "test_hi182x_common.h"

using namespace dev;

namespace drivers {
namespace pcie_nic_card {
namespace hisi {
namespace test {

// ========================= NicPort设备测试 =========================

TEST_F(Hi182xAbiTest, create_hi182x_port_success) {
    // 目标：验证NicPort设备创建成功
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    // 使用构造函数创建网口设备实例
    auto device = device_driver->ctor(&m_test_service, "hi182x_port");
    ASSERT_TRUE(device != nullptr);
}

TEST_F(Hi182xAbiTest, create_hi182x_port_null_service) {
    // 目标：验证创建网口设备时传入空服务指针的错误处理
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    // 测试：传入空服务指针应该返回nullptr
    auto device = device_driver->ctor(nullptr, "hi182x_port");
    EXPECT_EQ(device, nullptr);
}

TEST_F(Hi182xAbiTest, init_hi182x_port_null_params) {
    // 目标：验证使用空参数初始化网口设备时的错误处理
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = device_driver->ctor(&m_test_service, "hi182x_port_null_test");
    ASSERT_TRUE(device != nullptr);

    // 测试：使用空参数初始化应返回错误
    status_t ret = device_driver->init(device, nullptr, nullptr);
    EXPECT_EQ(ret, STATUS_ERROR);
}

TEST_F(Hi182xAbiTest, init_hi182x_port_with_params) {
    // 目标：验证网口设备的初始化功能
    // 测试：设置PortId和MACAddress配置参数
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_port*>(
        device_driver->ctor(&m_test_service, "hi182x_port_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 配置网口参数：端口ID和MAC地址
    auto config = mc::mutable_dict({
        {"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}, {"MACAddress", "00:11:22:33:44:55"}}}
    });
    
    // 执行初始化
    EXPECT_TRUE(device->init(config, mc::dict()));
    
    // 验证配置参数设置成功
    EXPECT_EQ(device->m_network_port.PortId.get_value(), 1);
    EXPECT_EQ(device->m_network_port.MACAddress.get_value(), "00:11:22:33:44:55");
}

TEST_F(Hi182xAbiTest, test_hi182x_NetworkPort_start_with_om) {
    // 目标：验证网口设备与单个光模块组合的启动和停止功能
    // 场景：网口->光模块的正常层级结构
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_port*>(
        device_driver->ctor(&m_test_service, "hi182x_port_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 初始化网口设备
    auto config = mc::mutable_dict({
        {"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}, {"MACAddress", "00:11:22:33:44:55"}}}
    });
    EXPECT_TRUE(device->init(config, mc::dict()));
    
    // 创建并挂载光模块
    auto om_device = static_cast<hi182x_optical_module*>(
        device_driver->ctor(&m_test_service, "OpticalTransceiver_om1"));
    ASSERT_TRUE(om_device != nullptr);
    om_device->set_parent(device);

    // 启动和停止应该成功
    EXPECT_TRUE(device->start());
    EXPECT_TRUE(device->stop());
}

TEST_F(Hi182xAbiTest, test_hi182x_NetworkPort_start_multiple_om) {
    // 目标：验证一个网口挂载多个光模块时的错误处理
    // 场景：一个网口只能有一个光模块，多个光模块应导致启动失败
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_port*>(
        device_driver->ctor(&m_test_service, "hi182x_port_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    auto config = mc::mutable_dict({
        {"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}, {"MACAddress", "00:11:22:33:44:55"}}}
    });
    EXPECT_TRUE(device->init(config, mc::dict()));
    
    auto om_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(om_driver != nullptr);

    // 创建第一个光模块
    auto om_device1 = static_cast<hi182x_optical_module*>(
        om_driver->ctor(&m_test_service, "hi182x_om1"));
    ASSERT_TRUE(om_device1 != nullptr);
    om_device1->set_parent(device);

    // 创建第二个光模块（非法：一个网口只能有一个光模块）
    auto om_device2 = static_cast<hi182x_optical_module*>(
        om_driver->ctor(&m_test_service, "hi182x_om2"));
    ASSERT_TRUE(om_device2 != nullptr);
    om_device2->set_parent(device);

    // 启动应该失败
    EXPECT_FALSE(device->start());
    EXPECT_TRUE(device->stop());
}

TEST_F(Hi182xAbiTest, test_hi182x_NetworkPort_verify_did_vid_svid_sdid) {
    // 目标：验证网口设备的VID/DID/SVID/SDID验证功能
    // 场景：通过PCIe配置空间验证设备身份
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_port*>(
        device_driver->ctor(&m_test_service, "hi182x_port_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    auto config = mc::mutable_dict({
        {"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}, {"MACAddress", "00:11:22:33:44:55"}}}
    });
    EXPECT_TRUE(device->init(config, mc::dict()));

    // 模拟PCIe设备信息
    imu_pcie_device_req_t pcie_device_info;
    pcie_device_info.bus = 0;
    pcie_device_info.device = 0;
    pcie_device_info.function = 0;

    // 验证设备ID信息不应抛出异常
    EXPECT_NO_THROW({
        device->verify_did_vid_svid_sdid(pcie_device_info);
    });
    
    // 数据格式：{0xe5, 0x19, 0x22, 0x18}
    // device_id = data[3] + (data[2] << 8) = 0x18 + (0x22 << 8) = 0x2218
    // vendor_id = data[1] + (data[0] << 8) = 0x19 + (0xe5 << 8) = 0xe519
    std::vector<uint8_t> vid_did_data = {0xe5, 0x19, 0x22, 0x18};
    uint16_t device_id = (vid_did_data[3] & 0xff) | (vid_did_data[2] & 0xff) << 8;
    uint16_t vendor_id = (vid_did_data[1] & 0xff) | (vid_did_data[0] & 0xff) << 8;
    
    EXPECT_EQ(vendor_id, 0xe519);
    EXPECT_EQ(device_id, 0x2218);
    EXPECT_FALSE(vendor_id == 0xffff && device_id == 0xffff);
    
    std::vector<uint8_t> invalid_data = {0xFF, 0xFF, 0xFF, 0xFF};
    uint16_t invalid_device_id = (invalid_data[3] & 0xff) | (invalid_data[2] & 0xff) << 8;
    uint16_t invalid_vendor_id = (invalid_data[1] & 0xff) | (invalid_data[0] & 0xff) << 8;
    
    EXPECT_EQ(invalid_vendor_id, 0xFFFF);
    EXPECT_EQ(invalid_device_id, 0xFFFF);
    EXPECT_TRUE(invalid_vendor_id == 0xffff && invalid_device_id == 0xffff);
    
    std::vector<uint8_t> short_data = {0xe5, 0x19};
    EXPECT_LT(short_data.size(), 4);
    
    const uint8_t VID_DID_ADDRESS = 0x00;
    const uint8_t SVID_SDID_ADDRESS = 0x2C;
    EXPECT_EQ(VID_DID_ADDRESS, 0x00);
    EXPECT_EQ(SVID_SDID_ADDRESS, 0x2C);
}

TEST_F(Hi182xAbiTest, test_hi182x_NetworkPort_update_port_bdf) {
    // 目标：验证网口设备的BDF（Bus/Device/Function）更新功能
    // 场景：根据PortId偏移计算实际的PCIe总线地址
    auto device_driver = m_devices["NicPort"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_port*>(
        device_driver->ctor(&m_test_service, "hi182x_port_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 初始化网口设备
    auto config = mc::mutable_dict({
        {"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}, {"MACAddress", "00:11:22:33:44:55"}}}
    });
    EXPECT_TRUE(device->init(config, mc::dict()));
    
    // 模拟PCIe设备信息
    imu_pcie_device_req_t pcie_device_info;
    pcie_device_info.bus = 0;
    pcie_device_info.device = 0;
    pcie_device_info.function = 0;

    // 更新BDF不应抛出异常
    EXPECT_NO_THROW({
        device->update_port_bdf(pcie_device_info);
    });
    
    // 验证BDF计算逻辑：bus = original_bus + PortId
    uint8_t original_bus = 0;
    uint8_t port_id = 1;
    uint8_t calculated_bus = original_bus + port_id;
    EXPECT_EQ(calculated_bus, 1);
    
    // 验证BDF字符串格式 (格式: Bus:Device.Function)
    std::string expected_bdf = std::to_string(calculated_bus) + ":" + 
                              std::to_string(pcie_device_info.device) + "." + 
                              std::to_string(pcie_device_info.function);
    EXPECT_EQ(expected_bdf, "1:0.0");
    
    // 验证设备属性未被修改
    EXPECT_EQ(device->m_network_port.PortId, 1);
    EXPECT_EQ(device->m_network_port.MACAddress.get_value(), "00:11:22:33:44:55");
}

} // namespace test
} // namespace hisi
} // namespace pcie_nic_card
} // namespace drivers

